home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d20 / msgq160s.arc / CONFIG.C < prev    next >
Text File  |  1991-10-26  |  46KB  |  1,816 lines

  1. /*
  2.  * CONFIG.C - Config file
  3.  *
  4.  * Msged/Q message editor for QuickBBS  Copyright 1990 by P.J. Muller
  5.  *
  6.  */
  7.  
  8. #define TEXTLEN 200
  9. #define BUFSIZE 4096    /* buffer size for config files */
  10.  
  11. #define TOSSCAN        /* last-minute addition, Local for TosScan */
  12.  
  13. #include <stdlib.h>
  14. #include <string.h>
  15. #include <stdio.h>
  16. #include <io.h>
  17. #include <ctype.h>
  18. #include <fcntl.h>
  19. #include <mem.h>
  20. #if defined(__TURBOC__) || defined(__JPIC__)
  21. #include <dir.h>
  22. #endif
  23. #ifdef __MSC__
  24. #include <sys/types.h>
  25. #endif
  26. #include <sys/stat.h>
  27.  
  28. #include "msged.h"
  29. #include "screen.h"
  30. #include "editmail.h"
  31. #include "maincmds.h"
  32. #include "p2c.h"
  33. #include "shell.h"
  34. #include "ra.h"
  35.  
  36. enum {A_LOCAL=1, A_NETM, A_ECHO};    /* area types */
  37. enum {F_PRIV=1, F_CRASH=2, F_KILL=4, F_SOFT=8};    /* flag bits */
  38. enum {INFO,WARN,ERR,FATAL};        /* log types */
  39.  
  40. static int insertarea;            /* position for inserting next area */
  41.                     /* if -1, insert at end */
  42.  
  43. static int initerrors;            /* number of errors */
  44. static int initwarnings;        /* number of warnings */
  45.  
  46. #ifdef TOSSCAN
  47. static BOOLEAN tosscan = FALSE;
  48. #endif
  49.  
  50. static void checkareas(char *cpath);
  51. static void set_colors(char *keyword,char *value);
  52. static void init(void);
  53. static void parsemail(char *keyword, char *value);
  54. static void parseconfig(FILE *fp);
  55. static unsigned int *parse_macro(char *macro);
  56. static void addarea(char *tag, char *desc, BYTE board, BYTE areatype,
  57.     BYTE flag, BYTE aka, char *orig);
  58. static void readconfigbbs(void);
  59. static void createconfigbbs(void);
  60. static void readraconfigs(void);
  61. void checkorig(void);
  62. /* Not for tc++ static int numlookup(struct _nentry *tab, char *val); */
  63. static void log(BYTE type, char *msg, char *param);
  64. static void verifyorigin(char *origin, ADDRESS addr);
  65. #ifdef DBRIDGE
  66. static void readdbridgeprm(void);
  67. static void readdbridgeconfigs(void);
  68. static void readdbridgeprm(void);
  69. #endif
  70.  
  71. /*
  72.  * Config keyword dispatcher jump table
  73.  */
  74.  
  75. struct _centry {
  76.     char *label;
  77.     void (*action)(char *keyword, char *value);
  78. };
  79.  
  80. struct _nentry {
  81.     char *label;
  82.     int value;
  83. };
  84.  
  85. struct _ientry {
  86.     char *label;
  87.     int *value;
  88. };
  89.  
  90. static unsigned int *parse_macro(char *macro)
  91. {
  92.     unsigned int *m;
  93.     unsigned int *t;
  94.     char tmp[5];
  95.  
  96.     t = m = (unsigned int *) calloc(strlen(macro), sizeof(int));
  97.  
  98.     if ((t == NULL) || (macro == NULL))
  99.         return(NULL);
  100.  
  101.     while (*macro) {
  102.         if (*macro == '^') {
  103.             if (*(macro + 1) == '^')
  104.                 *t++ = (unsigned int) '^';
  105.             else
  106.                 *t++ = (unsigned int) (toupper(*(macro + 1)) - 64);
  107.             macro += 2;
  108.         }
  109.         else if (*macro == '\\') {
  110.             if (*(macro + 1) != '0') {    /* escape */
  111.                 *t++ = (unsigned int) *(++macro);
  112.                 ++macro;
  113.             }    /* must be of form '\0xhh' */
  114.             else {
  115.                 memset(tmp,0,sizeof tmp);
  116.                 strncpy(tmp,macro+1,4);
  117.                 *t++ = (unsigned int) strtol(tmp,NULL,0) << 8;
  118.                 macro += 5;
  119.             }
  120.         }
  121.         else
  122.             *t++ = (unsigned int) *macro++;
  123.     }
  124.  
  125.     *t = 0;
  126.  
  127.     return(m);
  128. } /* parse_macro */
  129.  
  130. static void log(BYTE type, char *msg, char *param)
  131. {
  132.   char ch;
  133.  
  134.   switch (type) {
  135.     case INFO:
  136.       if (!configdebug) return;
  137.       ch = ' ';
  138.       break;
  139.     case WARN:
  140.       if (!configdebug) return;
  141.       ++initwarnings;
  142.       ch = '-';
  143.       break;
  144.     case ERR:
  145.       ++initerrors;
  146.       ch = '!';
  147.       break;
  148.     case FATAL:
  149.       ++initerrors;
  150.       ch = '?';
  151.       break;
  152.     default:
  153.       ch = '#';
  154.       break;
  155.   } /* switch */
  156.  
  157.   printf("%c ",ch);
  158.   printf(msg,param);
  159.   printf("\n");
  160.  
  161.   if (type == FATAL) {
  162.     printf("  A fatal error occurred, I cannot continue.\n");
  163.     halt(255);
  164.   } /* if */
  165.  
  166. } /* log */
  167.  
  168. void    opening(char *cfgfile, char *areafile, char *uname)
  169. {
  170.     int y, c;
  171.     FILE *fp = NULL;
  172.     char fname[TEXTLEN];
  173.  
  174.     initerrors = initwarnings = 0;
  175.  
  176.     init();            /* set defaults */
  177.     insertarea = -1;    /* insert areas at end */
  178.  
  179.     if (createconfig)
  180.       log(INFO,"Will create new CONFIG.BBS with netmailpath '%s'",newnetpath);
  181.  
  182.     if (quicksysop) {     /* first read CONFIG.BBS if needed */
  183.       log(INFO, "Reading QuickBBS configs", NULL);
  184.       readconfigbbs();
  185.     }
  186.  
  187.     if (rastruct) {     /* read RA messages file if needed */
  188.       log(INFO, "Reading RemoteAccess configs", NULL);
  189.       readraconfigs();
  190.     }
  191.  
  192. #ifdef DBRIDGE
  193.     if (dbridgestruct) {     /* read D'Bridge messages file if needed */
  194.       log(INFO, "Reading D'Bridge configs", NULL);
  195.       readdbridgeconfigs();
  196.     }
  197. #endif
  198.  
  199. /*- Moved here 22/01/90 -*/
  200.     checkareas(areafile);        /* read areas.bbs */
  201.  
  202.     /* start looking for the ascii config file... */
  203.  
  204.     fname[0] = EOS;
  205.     if (cfgfile != NULL) {        /* first try the specified file */
  206.       strcpy(fname,cfgfile);
  207.       fp = fopen(fname,"rt");
  208.     } /* if */
  209.  
  210.     if (fp == NULL) {        /* now try $BINKLEY\binkley.cfg */
  211.       char *env = getenv("BINKLEY");
  212.  
  213.       fname[0] = EOS;
  214.       if (env != NULL) {
  215.         strcpy(fname,env);
  216.         if (strchr("/\\",fname[strlen(fname)-1]) == NULL)
  217.           strcat(fname,"\\");
  218.       } /* if */
  219.       strcat(fname,"binkley.cfg");
  220.  
  221.       fp = fopen(fname,"rt");
  222.     } /* if */
  223.  
  224.     if (fp == NULL) {        /* now try msged.cfg */
  225.       strcpy(fname,"msged.cfg");
  226.       fp = fopen(fname,"rt");
  227.     } /* if */
  228.  
  229.     if (fp == NULL) {        /* now try msgedq.cfg */
  230.       strcpy(fname,"msgedq.cfg");
  231.       fp = fopen(fname,"rt");
  232.     } /* if */
  233.  
  234.     if (fp != NULL) {        /* we found a file */
  235.       char *buf = malloc(BUFSIZE);
  236.  
  237.       log(INFO,"Reading '%s'", fname);
  238.  
  239.       if (buf != NULL)
  240.         setvbuf(fp,buf,_IOFBF,BUFSIZE);
  241.  
  242.       insertarea = 0;        /* insert at front */
  243.       parseconfig(fp);
  244.  
  245.       if (fp != NULL)
  246.         fclose(fp);
  247.  
  248.       if (buf != NULL)
  249.         ptrfree(buf);
  250.         } /* if */
  251.  
  252.         video_init();
  253.  
  254.     if (co_quote == 0)
  255.       co_quote = co_normal;
  256.  
  257.     if (rm > maxx)
  258.       rm = maxx - 1;
  259.     if (quoteright > rm-15)
  260.       quoteright = rm-15;
  261.     else if (quoteright < 20)
  262.       quoteright = 20;
  263.  
  264.     if (uname != NULL) {        /* override */
  265.       if (username != NULL) ptrfree(username);
  266.       username = strdup(uname);
  267.       log(INFO,"Command line username override '%s'", username);
  268.     }
  269.  
  270.     if ((username == NULL) || (addresses == 0))
  271.       log(FATAL,"I could not find a username or address",NULL);
  272.  
  273.     if (areas == 0)
  274.       log(FATAL,"I hate to mention the obvious, but you defined no areas!",NULL);
  275.  
  276. #ifdef TOSSCAN
  277.   if (tosscan) {
  278.     int c;
  279.     for (c=0;  c < areas;  c++)
  280.       arealist[c].msgbits.is_local = 1;    /* all messages local */
  281.   } /* if */
  282. #endif
  283.  
  284.     if (createconfig)
  285.       if (quicksysop)
  286.         log(ERR,"I won't create CONFIG.BBS for you, a QuickBBS sysop should use QCONFIG",NULL);
  287.       else
  288.         createconfigbbs();
  289.  
  290.     if (useusersbbs) {
  291.       if ((usernum = searchuser(username, TRUE)) == -1) {
  292.         log(ERR,"Could not find user '%s', defaulting to UserNumber 0\n",username);
  293.         usernum = 0;
  294.           } /* if */
  295.     } else usernum = 0;        /* if USERS.BBS not searched */
  296.  
  297.     checkorig();            /* Check for origin overrides */
  298.  
  299.     if (createconfig) {
  300.       log(INFO, "Exit after rebuilding CONFIG.BBS",NULL);
  301.       halt(200);
  302.     } /* if */
  303.  
  304.     if (configdebug || (initerrors != 0) || (initwarnings != 0)) {
  305.       if (initerrors != 0) {
  306.         log(ERR,"Pardon me, I think I spotted something wrong.",NULL);
  307.         if (!configdebug)
  308.           printf("Try the -d command line switch to debug your config file.\n");
  309.       } else if (initwarnings != 0) {
  310.         log(WARN,"I saw some warnings above...",NULL);
  311.       } /* else */
  312.  
  313.       printf("Press <Return> to continue please:");
  314.       while (getkey() != 0x0d)
  315.         /* loop */;
  316.     } /* if */
  317.  
  318.     set_color(co_normal);
  319.     cls();
  320.     gotoxy(1, maxy);  video_update();
  321.  
  322.     gotoxy(1, y=1);
  323.     set_color(co_hilite);
  324.     bputs("------------------------------------------------------------------------------");
  325.     set_color(co_normal);
  326.     gotoxy(10, y+=2);
  327.     bputs("Msged/Q " VERSION " - QuickBBS/RemoteAccess Compatible Mail Editor");
  328.     set_color(co_normal);
  329.     gotoxy(10, y+=2);
  330.     bputs("Copyright 1991 by Pieter Muller, 5:7102/11"
  331. #ifdef __DATE__
  332.     " (" __DATE__ ")"
  333. #endif
  334.     );
  335.     gotoxy(10, y+=2);
  336.     bputs("Based on msged 1.99 by Jim Nutt");
  337.  
  338.     gotoxy(1, y+=2);
  339.     set_color(co_hilite);
  340.     bputs("---- SETUP -------------------------------------------------------------------");
  341.     set_color(co_info);
  342.     gotoxy(1, y+=2);
  343.     bprintf("    Sysop: %s", username);
  344.     for (c=0; c < addresses;  ++c) {
  345.       char pointstr[80];
  346.  
  347.       if ((thisnode[c].point) && (pointnet != 0))
  348.         sprintf(pointstr, "(private net %d/%d)", pointnet, thisnode[c].point);
  349.       else
  350.         pointstr[0] = EOS;
  351.  
  352.       gotoxy(1, ++y);
  353.       bprintf("%9s: %s %s",    c==0 ? "Address" : "AKA",
  354.                 formaddr(thisnode[c], Z_A|N_A|P_O|D_O),
  355.                 pointstr);
  356.     }
  357.     { char buffer[200];
  358.       formatorigin(buffer, origin, thisnode[0]);
  359.       gotoxy(1, ++y);
  360.       bputs(buffer);
  361.     }
  362.     gotoxy(1, ++y);
  363.     bprintf("Msg Areas: %d found", areas);
  364.     gotoxy(1, ++y);
  365.     bprintf("    Video: %d by %d ", maxx, maxy);
  366.     switch (videomethod) {
  367.       case DIRECT:
  368.         bputs("direct");    break;
  369.       case BIOS:
  370.         bputs("bios");    break;
  371.       case FOSSIL:
  372.         bputs("fossil");    break;
  373.       case NOSNOW:
  374.         bputs("no-snow");    break;
  375.     } /* switch */
  376.  
  377.     set_color(co_normal);
  378.     gotoxy(1,y+2);
  379.  
  380. } /* opening */
  381.  
  382. ADDRESS parsenode(char *t)
  383. {
  384.     ADDRESS tmp;
  385.     char   *s = NULL, *str = NULL;
  386.  
  387.     memset(&tmp, 0, sizeof tmp);
  388.  
  389.     if ((s = strrchr(t,'@')) != NULL) {
  390.         size_t len;
  391.         tmp.domain = strdup(s + 1);
  392.         len = strcspn(tmp.domain, " \t\n\r;");
  393.         tmp.domain[len] = EOS;
  394.     } else
  395.         tmp.domain = NULL;
  396.  
  397.     str = s = strdup(t);
  398.  
  399.     if (strchr(t, ':')) {
  400.         tmp.zone = (int) strtol(strtok(s, ":"),NULL,0);
  401.         if (strchr(t, '/')) {
  402.             tmp.net = (int) strtol(s = strtok(NULL, "/"),NULL,0);
  403.             if (strchr(t, '.')) {
  404.                 tmp.node = (int) strtol(s = strtok(NULL, "."),NULL,0);
  405.                 tmp.point = (int) strtol(strtok(NULL, "\0"),NULL,0);
  406.             }
  407.             else {
  408.                 tmp.point = 0;
  409.                 tmp.node = (int) strtol(strtok(NULL, "\0"),NULL,0);
  410.             }
  411.         }
  412.         else {
  413.             tmp.net = thisnode[0].net;
  414.             if (strchr(t, '.')) {
  415.                 tmp.node = (int) strtol(strtok(s, "."),NULL,0);
  416.                 tmp.point = (int) strtol(strtok(NULL, "\0"),NULL,0);
  417.             }
  418.             else {
  419.                 tmp.point = 0;
  420.                 tmp.node = (int) strtol(s,NULL,0);
  421.             }
  422.         }
  423.     }
  424.     else {
  425.         tmp.zone = thisnode[0].zone;
  426.         if (strchr(t, '/')) {
  427.             tmp.net = (int) strtol(strtok(s, "/"),NULL,0);
  428.             if (strchr(t, '.')) {
  429.                 tmp.node = (int) strtol(strtok(NULL, "."),NULL,0);
  430.                 tmp.point = (int) strtol(strtok(NULL, "\0"),NULL,0);
  431.             }
  432.             else {
  433.                 tmp.point = 0;
  434.                 tmp.node = (int)strtol(strtok(NULL, "\0"),NULL,0);
  435.             }
  436.         }
  437.         else {
  438.             tmp.net = thisnode[0].net;
  439.             if (strchr(t, '.')) {
  440.                 tmp.node = (int) strtol(s = strtok(s, "."),NULL,0);
  441.                 tmp.point = (int) strtol(s = strtok(NULL, "\0"),NULL,0);
  442.             }
  443.             else {
  444.                 tmp.point = 0;
  445.                 tmp.node = (int) strtol(s,NULL,0);
  446.             }
  447.         }
  448.     }
  449.     ptrfree(str);
  450.     return (tmp);
  451. }
  452.  
  453. static void checkareas(char *areafile)
  454. {
  455.     char buffer[TEXTLEN];
  456.     char path[PATHLEN];
  457.     char *fname;
  458.     char *s = NULL;
  459.     int flag = 1;
  460.     FILE *fp;
  461.  
  462.     strcpy(path,bbspath);
  463.     strcat(path,"areas.bbs");
  464.  
  465.     fp = NULL;
  466.     if (areafile != NULL)
  467.       fp = fopen(fname = areafile,"rt");
  468.     if (fp == NULL)
  469.       fp = fopen(fname = path,"rt");
  470.     if (fp == NULL)
  471.       fp = fopen(fname = "areas.bbs","rt");
  472.     if (fp == NULL)
  473.       return;
  474.  
  475.     log(INFO,"Reading '%s'",fname);
  476.  
  477.      if (fp != NULL) {
  478.         while (fgets(buffer, TEXTLEN, fp) != NULL) {
  479.             char *tag = NULL;
  480.             BYTE board;
  481.  
  482.             if ((*buffer == '\r') || (*buffer == '\n'))
  483.                 continue;
  484.  
  485.             s = buffer;
  486.  
  487.             while (isspace(*s))
  488.                 s++;
  489.  
  490.             if ((*s == ';') || (*s == '-'))
  491.                 continue;
  492.  
  493.             if ((strchr(buffer,'!')) && flag) {
  494.                                 char *p = strrchr(buffer,'!');
  495.                                 if (p != NULL) {
  496.                                         *p = '\0';
  497.                                         if (origin != NULL)
  498.                       ptrfree(origin);
  499.                     origin = strdup(buffer);
  500.                     verifyorigin(origin,thisnode[0]);
  501.                                 }
  502.                                 flag = 0;
  503.                 continue;
  504.             }
  505.  
  506.             board = atoi(strtok(s," \t"));
  507.             tag = strtok(NULL," \t\n");
  508.                         flag = 0;
  509.  
  510.             addarea(tag, NULL, board, A_ECHO, 0, 0, NULL);
  511.         } /* while */
  512.     } /* if */
  513.  
  514.     if (fp != NULL)
  515.         fclose(fp);
  516. } /* checkareas */
  517.  
  518. /*
  519.  * Add or modify an area
  520.  * One of tag or desc may be NULL
  521.  */
  522.  
  523. static void addarea(char *tag, char *desc, BYTE board, BYTE areatype,
  524.     BYTE flag, BYTE aka, char *orig)
  525. {
  526.   int i;
  527.  
  528.   if (board == 0) return;        /* Passthrough area... */
  529.  
  530. #ifdef DEBUGAREAS
  531.   printf("\nAdding %d %s %s\n", board, tag, desc);
  532.   for (i = 0;  i < areas;  i++)
  533.     printf("%d %s %s\n", arealist[i].board, arealist[i].tag,
  534.        arealist[i].description);
  535. #endif
  536.  
  537.   for (i = 0;  i < areas;  i++)        /* look for the board */
  538.     if (arealist[i].board == board)
  539.       break;                /* found? */
  540.  
  541.   if (i == areas) {            /* new area... */
  542.     areas++;
  543.     area = areas - 1;
  544.     if (arealist == NULL) {
  545.       arealist = malloc(areas * sizeof(AREA));
  546.       checkmem(arealist);
  547.     } else {
  548.       arealist = realloc(arealist, areas * sizeof(AREA));
  549.       checkmem(arealist);
  550.     } /* else */
  551.  
  552.     if (insertarea >= 0) {
  553.       if (areas-1-insertarea > 0)
  554.     movmem(&arealist[insertarea],&arealist[insertarea+1],
  555.            (areas-1-insertarea)*sizeof(arealist[0]));    /* move up */
  556.       area = insertarea++;
  557.     } /* if */
  558.  
  559.     memset(&arealist[area],0,sizeof(AREA));    /* this also clears msgbits */
  560.  
  561.     switch (areatype) {
  562.       case A_LOCAL:    arealist[area].local = 1;
  563.             if (tag == NULL)
  564.               tag = "Local";
  565.             break;
  566.       case A_NETM:    arealist[area].netmail = 1;
  567.             if (tag == NULL)
  568.               tag = "Netmail";
  569.             break;
  570.       case A_ECHO:    arealist[area].echomail = 1;
  571.             if (tag == NULL)
  572.               tag = "Echomail";
  573.             break;
  574.     } /* switch */
  575.  
  576.     arealist[area].tag = strdup(tag);
  577.  
  578.     if (desc == NULL)
  579.       desc = arealist[area].tag;
  580.     arealist[area].description = strdup(desc);
  581.  
  582.     arealist[area].board = board;
  583.   } else {                /* old area... */
  584.     AREA temp = arealist[i];        /* save old */
  585.  
  586.     if (areas-i-1 > 0)
  587.       movmem(&arealist[i+1],&arealist[i],(areas-i-1)*sizeof(arealist[0]));
  588.                     /* move down to close gap */
  589.     if (insertarea >= 0) {
  590.       if (areas-1-insertarea > 0)
  591.     movmem(&arealist[insertarea],&arealist[insertarea+1],
  592.            (areas-1-insertarea)*sizeof(arealist[0]));    /* move up */
  593.       area = insertarea++;
  594.     } else {
  595.       area = areas-1;
  596.     } /* else */
  597.  
  598.     arealist[area] = temp;        /* restore old */
  599.  
  600.     if ((tag != NULL) && (*tag != EOS)) {    /* modify old tag */
  601.       if (arealist[area].tag != NULL)
  602.     ptrfree(arealist[area].tag);
  603.       arealist[area].tag = strdup(tag);
  604.     } /* if */
  605.  
  606.     if ((desc != NULL) && (*desc != EOS)) {    /* modify old desc */
  607.       if (arealist[area].description != NULL)
  608.     ptrfree(arealist[area].description);
  609.       arealist[area].description = strdup(desc);
  610.     } /* if */
  611.  
  612.   } /* else */
  613.  
  614.   if (flag & F_PRIV)
  615.     arealist[area].msgbits.is_priv = 1;
  616.   if (flag & F_CRASH)
  617.     arealist[area].msgbits.is_crash = 1;
  618.   if (flag & F_KILL)
  619.     arealist[area].msgbits.is_kill = 1;
  620.   if (flag & F_SOFT)
  621.     arealist[area].softcr = 1;
  622.   arealist[area].aka = aka;
  623.  
  624.   if (orig != NULL) {
  625.     arealist[area].areaorig = strdup(orig);
  626.     verifyorigin(orig, thisnode[0]);
  627.   }
  628.  
  629. } /* addarea */
  630.  
  631. static void init()
  632. {
  633.   memset(macros,0,sizeof(macros));
  634.   shownotes = NO;
  635.  
  636.   memset(&thisnode,0,sizeof(thisnode));
  637.   addresses = 0;
  638.  
  639.   username = NULL;
  640.   outfile = strdup("prn");
  641.   domains = 0;
  642.   domain_list = NULL;
  643.   tabsize = 8;
  644.   pointnet = 0;
  645.   override = FALSE;
  646. #ifdef SEENBY
  647.   seenbys = NO;
  648. #endif
  649. #ifdef GATE
  650.   gate = 7;
  651. #endif
  652. #ifdef TEARLINE
  653.   tearline = YES;
  654. #endif
  655.   quotestr = strdup(">");
  656.   attribline = strdup("In a message of <$d>, $f ($a) writes:");
  657.   areas = 0;
  658.   fidolist = NULL;
  659.   userlist = NULL;
  660.   origin = NULL;
  661.   confirmations = YES;
  662.   videomethod = DIRECT;
  663.   vbase = 0;
  664.   maxx = maxy = 0;
  665.   co_normal = 0x07;
  666.   co_quote  = 0;
  667.   co_warn   = 0x0f;
  668.   co_block  = 0x0f;
  669.   co_info   = 0x07;
  670.   co_hilite = 0x70;
  671.   quoteright = rm = 300;        /* an unreasonable value */
  672.  
  673.   checkmem(bbspath = malloc(PATHLEN));
  674.   if (getcwd(bbspath, PATHLEN) == NULL)
  675.     strcpy(bbspath,".");
  676.   if (bbspath[strlen(bbspath)-1] != '\\')
  677.     strcat(bbspath,"\\");
  678.   checkmem(bbspath = realloc(bbspath,strlen(bbspath)+1));
  679.   beepson = YES;
  680.   msgids = ON;
  681. #ifdef EIDS
  682.   eids = ON;
  683. #endif
  684.   strip = ON;
  685.   globsrch = ON;
  686.   techie = OFF;
  687. } /* init */
  688.  
  689. /*
  690.  * Handle local, mail and echo statements from the config file
  691.  */
  692.  
  693. static void parsemail(char *keyword, char *value)
  694. {
  695.   char *key;
  696.   char desc[PATHLEN];
  697.   char tag[PATHLEN];
  698.   char *s = NULL, *d, ch;
  699.   BYTE type = A_LOCAL;
  700.   BYTE bits;
  701.   BYTE board, aka = 0;
  702.  
  703.   key = keyword;
  704.   keyword = strtok(value," \t");
  705.   value = strtok(NULL,";\n\r");
  706.  
  707.   if (stricmp("local", keyword) == 0)
  708.     type = A_LOCAL;
  709.   else if (stricmp("mail", keyword) == 0)
  710.     type = A_NETM;
  711.   else if (stricmp("echo", keyword) == 0)
  712.     type = A_ECHO;
  713.   else return;
  714.  
  715.   bits = 0;
  716.   d = value;
  717.   while ((*d != EOS) && (*d != '"'))
  718.     switch (tolower(ch = *d++)) {
  719.       case 'p':
  720.     bits |= F_PRIV;        break;
  721.       case 'c':
  722.     bits |= F_CRASH;    break;
  723.       case 'k':
  724.     bits |= F_KILL;        break;
  725.       case 's':
  726.     bits |= F_SOFT;        break;
  727.       case '1':
  728.       case '2':
  729.       case '3':
  730.       case '4':
  731.       case '5':            /* MAXAKA */
  732.     aka = (ch-'0');        break;
  733.     } /* switch */
  734.  
  735.   if (*d == EOS)
  736.     goto error;
  737.  
  738.   s = ++d;
  739.   d = desc;
  740.   while ((*s != EOS) && (*s != '"'))
  741.     *d++ = *s++;
  742.   *d = EOS;
  743.  
  744.   s++;                    /* skip delimiter */
  745.  
  746.   d = tag;
  747.  
  748.   while ((*s != EOS) && isspace(*s)) s++;    /* skip spaces */
  749.  
  750.   if (*s == EOS) {
  751.     goto error;
  752.   } else {
  753.     while ((*s != EOS) && !isspace(*s))    /* get next keyword */
  754.       *d++ = *s++;
  755.     *d = EOS;
  756.     board = atoi(tag);
  757.  
  758.     if (type == A_ECHO) {            /* look for tag */
  759.       while ((*s != EOS) && isspace(*s)) s++;    /* skip spaces again */
  760.  
  761.       if (*s != NULL) {                /* More! */
  762.     d = tag;
  763.     while ((*s != EOS) && !isspace(*s))
  764.       *d++ = *s++;
  765.     *d = '\0';
  766.       } /* if */
  767.       d = tag;                /* tag for echomail */
  768.     } else {
  769.       d = NULL;                /* don't modify tag of Net/Local */
  770.     } /* else */
  771.  
  772.     addarea(d, desc, board, type, bits, aka, NULL);
  773.   } /* else */
  774.  
  775.   return;
  776.  
  777. error:
  778.   log(ERR,"Syntax error in '%s' statement", key);
  779. } /* parsemail */
  780.  
  781. /*
  782.  * Parse a string with possible quotes (" or ') and return
  783.  * malloc'ed string
  784.  */
  785.  
  786. char *parse_string(char *s)
  787. {
  788.   char *t, *orgt;
  789.   char delimit = ';';
  790.  
  791.   orgt = t = malloc(strlen(s)+1);
  792.   if ((s == NULL) || (t == NULL)) return(NULL);
  793.  
  794.   while (isspace(*s)) s++;    /* skip whitespace */
  795.   if ((*s == '\'') || (*s == '"'))
  796.     delimit = *s++;
  797.  
  798.   while ((*s != delimit) && (*s != EOS))
  799.     *t++ = *s++;
  800.   *t = EOS;
  801.  
  802.   return(realloc(orgt,strlen(orgt)+1));
  803. } /* parse_string */
  804.  
  805. #ifdef __TURBOC__
  806. #pragma warn -par    /* avoid stupid warnings about jmptable funcs */
  807. #endif
  808. #ifdef __JPIC__
  809. #pragma warn(wpnu => off)
  810. #endif
  811.  
  812. static void getusername(char *k, char *v);
  813. static void includeconfig(char *k, char *v);
  814. static void getoutfile(char *k, char *v);
  815. static void getnode(char *k, char *v);
  816. static void getvideo(char *k, char *v);
  817. static void getdomains(char *k, char *v);
  818. static void getorigin(char *k, char *v);
  819. static void getflags(char *k, char *v);
  820. static void getcolour(char *k, char *v);
  821. static void getuserlist(char *k, char *v);
  822. static void getfunction(char *k, char *v);
  823. static void getquote(char *k, char *v);
  824. static void getattrib(char *k, char *v);
  825. static void getquickbbs(char *k, char *v);
  826. static void getcols(char *k, char *v);
  827. static void getedit(char *k, char *v);
  828. static void getread(char *k, char *v);
  829. #ifdef GATE
  830. static void getgate(char *k, char *v);
  831. #endif
  832.  
  833. static struct _centry configtable[] = {
  834.     {"sysop",    getusername},        /* binkley    */
  835.     {"name",    getusername},        /* msged    */
  836.     {"include",    includeconfig},        /* binkley    */
  837.     {"outfile",    getoutfile},        /* msged    */
  838.     {"address",    getnode},        /* binkley    */
  839.     {"video",    getvideo},        /* msged    */
  840.     {"domain",    getdomains},        /* msged    */
  841.     {"origin",      getorigin},        /* msged    */
  842.     {"enable",    getflags},        /* msged/q    */
  843.     {"disable",    getflags},        /* msged/q    */
  844.     {"no",        getflags},        /* msged 2.00    */
  845.     {"colors",    getcolour},        /* binkley    */
  846.     {"colours",    getcolour},        /* msged    */
  847.     {"userlist",    getuserlist},        /* msged    */
  848.     {"function",    getfunction},        /* msged    */
  849.     {"quote",    getquote},        /* msged    */
  850.     {"attrib",    getattrib},        /* msged/q    */
  851.     {"quick",    parsemail},        /* msged 2.00    */
  852.     {"bbsfiles",    getquickbbs},        /* msged/q    */
  853.     {"quickbbs",    getquickbbs},        /* msged 2.00    */
  854.     {"color",    getcols},        /* msged    */
  855.     {"colour",    getcols},        /* msged    */
  856.     {"editkey",    getedit},        /* msged    */
  857.     {"readkey",    getread},        /* msged    */
  858. #ifdef GATE
  859.     {"gate",    getgate},        /* msged    */
  860. #endif
  861.     {NULL,        NULL}
  862. };
  863.  
  864. static struct _ientry oneinttable[] = {
  865.     {"videoseg",    (int *)&vbase},        /* msged    */
  866.     {"maxx",    &maxx},            /* msged    */
  867.     {"maxy",    &maxy},            /* msged    */
  868.     {"tabsize",    &tabsize},        /* msged    */
  869.     {"right",    &rm},            /* msged    */
  870.     {"quoteright",    "eright},        /* msged/q    */
  871.     {"privatenet",    &pointnet},        /* binkley    */
  872.     {NULL,        NULL}
  873. };
  874.  
  875. /*
  876.  * Display debugging info
  877.  */
  878.  
  879. static void logit(BOOLEAN ok, char *k, char *v)
  880. {
  881.   char buf[TEXTLEN];
  882.  
  883.   sprintf(buf,"%s\t%s",k,v);
  884.  
  885.   log(ok ? INFO : WARN, buf, NULL);
  886. } /* logit */
  887.  
  888. /*
  889.  * Look up in NULL terminated number table and return value
  890.  * Return the value paired with NULL if not found
  891.  * Lowercases the second argument
  892.  */
  893.  
  894. static int numlookup(struct _nentry *tab, char *val)
  895. {
  896.   strlwr(val);
  897.   while (tab->label != NULL) {
  898.     size_t len = strlen(tab->label);
  899.     if (strncmp(tab->label, val, len) == 0)
  900.       return tab->value;
  901.     tab++;
  902.   } /* while */
  903.  
  904.   log(WARN,"Unknown word '%s'", val);
  905.  
  906.   return tab->value;        /* return argument of NULL in table */
  907. } /* numlookup */
  908.  
  909. static void getusername(char *k, char *v)
  910. {
  911.   username = strdup(v);
  912. } /* getusername */
  913.  
  914. static void includeconfig(char *k, char *v)
  915. {
  916.   FILE *ifp;
  917.  
  918.   if ((ifp = fopen(v,"rt")) != NULL) {
  919.     char *buf = malloc(BUFSIZE);
  920.     log(INFO,"Including '%s'",v);
  921.     if (buf != NULL)
  922.       setvbuf(ifp,buf,_IOFBF,BUFSIZE);
  923.     parseconfig(ifp);
  924.     fclose(ifp);
  925.     if (buf != NULL)
  926.       ptrfree(buf);
  927.   } /* if */
  928.  
  929. } /* includeconfig */
  930.  
  931. static void getoutfile(char *k, char *v)
  932. {
  933.   ptrfree(outfile);
  934.   outfile = strdup(v);
  935. } /* getoutfile */
  936.  
  937. static void getnode(char *k, char *v)
  938. {
  939.   if (addresses >= MAXAKA) {
  940.     log(WARN, "Too many addresses defined", NULL);
  941.     return;
  942.   }
  943.   thisnode[addresses++] = parsenode(v);
  944. } /* getnode */
  945.  
  946. static void getvideo(char *k, char *v)
  947. {
  948.   static struct _nentry vmt[] = {
  949.     {"direct",    DIRECT},
  950.     {"nosnow",    NOSNOW},
  951.     {"bios",    BIOS},
  952.     {"fossil",    FOSSIL},
  953.     {NULL,        -1}
  954.   };
  955.   int i;
  956.  
  957.   if ((i = numlookup(vmt,v)) != -1)
  958.     videomethod = i;
  959.  
  960. } /* getvideo */
  961.  
  962. static void getdomains(char *k, char *v)
  963. {
  964.   char *s;
  965.   ADDRESS tdom;
  966.  
  967.   s = strdup(strtok(v," \t"));
  968.   tdom = parsenode(strtok(NULL,"\n"));
  969.   tdom.domain = s;
  970.   checkmem(domain_list = (ADDRESS *) realloc(domain_list,++domains * sizeof(ADDRESS)));
  971.   domain_list[domains - 1] = tdom;
  972. } /* getdomains */
  973.  
  974. static void getorigin(char *k, char *v)
  975. {
  976.   if (origin != NULL)
  977.     ptrfree(origin);
  978.   origin = strdup(v);
  979.   verifyorigin(origin,thisnode[0]);
  980. } /* getorigin */
  981.  
  982. /*
  983.  * Handle "disable xxx", "enable xxx" and "no xxx"
  984.  */
  985.  
  986. static void getflags(char *k, char *v)
  987. {
  988.   enum {UNKNOWN,SEENBYS,TEARLINE,SHOWNOTES,CONFIRM,MSGIDS,STRIP,
  989.     EIDSS,BEEPS,GLOBSRCH,TOSSSSSS,SWAPPING};
  990.   static struct _nentry vmt[] = {
  991.     {"shownotes",    SHOWNOTES},
  992.     {"confirm",    CONFIRM},
  993.     {"msgids",    MSGIDS},
  994.     {"strip",    STRIP},
  995.     {"beeps",    BEEPS},
  996.     {"globalsearch",GLOBSRCH},
  997.     {"swapping",    SWAPPING},
  998. #ifdef SEENBY
  999.     {"seen-bys",    SEENBYS},
  1000. #endif
  1001. #ifdef TEARLINE
  1002.     {"tearline",    TEARLINE},
  1003. #endif
  1004. #ifdef EIDS
  1005.     {"eids",    EIDSS},
  1006. #endif
  1007. #ifdef TOSSCAN
  1008.     {"tosscan",    TOSSSSSS},
  1009. #endif
  1010.     {NULL,        UNKNOWN}
  1011.   };
  1012.   BOOLEAN on;
  1013.  
  1014.   on = (stricmp(k,"enable") == 0);
  1015.  
  1016.   switch (numlookup(vmt,v)) {
  1017. #ifdef SEENBY
  1018.     case SEENBYS:    seenbys = on;        break;
  1019. #endif
  1020. #ifdef TEARLINE
  1021.     case TEARLINE:    tearline = on;        break;
  1022. #endif
  1023.     case SHOWNOTES:    shownotes = on;        break;
  1024.     case CONFIRM:       confirmations = on;    break;
  1025.     case MSGIDS:    msgids = on;        break;
  1026. #ifdef EIDS
  1027.     case EIDSS:        eids = on;        break;
  1028. #endif
  1029.     case STRIP:        strip = on;        break;
  1030.     case BEEPS:        beepson = on;        break;
  1031.     case GLOBSRCH:    globsrch = on;        break;
  1032.     case SWAPPING:      swapping_enabled = on;    break;
  1033. #ifdef TOSSCAN
  1034.     case TOSSSSSS:    tosscan = on;        break;
  1035. #endif
  1036.   } /* switch */
  1037.  
  1038. } /* getflags */
  1039.  
  1040. static void getcolour(char *k, char *v)
  1041. {
  1042.   co_quote = (int) strtol(strtok(v," \t"),NULL,0);
  1043.   co_warn = (int) strtol(strtok(NULL," \t"),NULL,0);
  1044.   co_block = (int) strtol(strtok(NULL," \t"),NULL,0);
  1045.   co_info = (int) strtol(strtok(NULL," \t"),NULL,0);
  1046.   co_normal = (int) strtol(strtok(NULL," \t"),NULL,0);
  1047.   co_hilite = (int) strtol(strtok(NULL," \t\n\r"),NULL,0);
  1048. } /* getcolour */
  1049.  
  1050. static void getuserlist(char *k, char *v)
  1051. {
  1052.   fidolist = strdup(strtok(v," ,\n"));
  1053.   if ((userlist = strtok(NULL," ,\n")) != NULL)
  1054.     userlist = strdup(userlist);
  1055. } /* getuserlist */
  1056.  
  1057. static void getfunction(char *k, char *v)
  1058. {
  1059.   int i;
  1060.   char *s;
  1061.  
  1062.   i = (int) strtol(v,&s,0) - 1;
  1063.  
  1064.   while (isspace(*s))
  1065.     s++;
  1066.  
  1067.   if ((i >= 0) && (i < 40))
  1068.     macros[i] = parse_macro(s);
  1069.  
  1070. } /* getfunction */
  1071.  
  1072. static void getquote(char *k, char *v)
  1073. {
  1074.   ptrfree(quotestr);
  1075.   quotestr = parse_string(v);
  1076. } /* getquote */
  1077.  
  1078. static void getattrib(char *k, char *v)
  1079. {
  1080.   ptrfree(attribline);
  1081.   attribline = parse_string(v);
  1082. } /* getattrib */
  1083.  
  1084. static void getquickbbs(char *k, char *v)
  1085. {
  1086.   if (v != NULL) {
  1087.     checkmem(bbspath = realloc(bbspath,strlen(v)+2));
  1088.     strcpy(bbspath,v);
  1089.     if (bbspath[strlen(bbspath)-1] != '\\')
  1090.       strcat(bbspath,"\\");
  1091.   } /* if */
  1092. } /* getquickbbs */
  1093.  
  1094. static void getcols(char *k, char *v)
  1095. {
  1096.   k = strtok(v," \t");
  1097.   v = strtok(NULL," \t");
  1098.   set_colors(k,v);
  1099. } /* getcols */
  1100.  
  1101. static void getedit(char *k, char *v)
  1102. {
  1103.   int scancode;
  1104.   int i = 0;
  1105.  
  1106.   strlwr(v);
  1107.   scancode = (int) strtol(v,&v,0);
  1108.   while (*v && isspace(*v)) v++;
  1109.   while (editcmds[i].label != NULL) {
  1110.     if (strncmp(editcmds[i].label,v,strlen(editcmds[i].label)) == 0) {
  1111.       if (scancode & 0xff)
  1112.     editckeys[scancode & 0xff] = editcmds[i].action;
  1113.       else
  1114.     editakeys[scancode >> 8] = editcmds[i].action;
  1115.       break;
  1116.     } /* if */
  1117.     i++;
  1118.   } /* while */
  1119. } /* getedit */
  1120.  
  1121. static void getread(char *k, char *v)
  1122. {
  1123.   int scancode;
  1124.   int i = 0;
  1125.  
  1126.   strlwr(v);
  1127.   scancode = (int) strtol(v,&v,0);
  1128.   while (*v && isspace(*v)) v++;
  1129.   while (maincmds[i].label != NULL) {
  1130.     if (strncmp(maincmds[i].label,v,strlen(maincmds[i].label)) == 0) {
  1131.       if (scancode & 0xff)
  1132.     mainckeys[scancode & 0xff] = maincmds[i].action;
  1133.       else
  1134.     mainakeys[scancode >> 8] = maincmds[i].action;
  1135.       break;
  1136.     } /* if */
  1137.     i++;
  1138.   } /* while */
  1139.  
  1140. } /* getread */
  1141.  
  1142. #ifdef GATE
  1143. **** untested code, should work... ****
  1144. static void getgate(char *k, char *v)
  1145. {
  1146.   if (gate == 7)
  1147.     gate = 0;
  1148.  
  1149.   strlwr(v);
  1150.  
  1151.   if (strncmp(v,"zones",5) == 0)
  1152.     gate |= GZONES;
  1153.   else if (strncmp(v,"domains",7) == 0)
  1154.     gate |= GDOMAINS;
  1155.   else if (strncmp(v,"both",4) == 0)
  1156.     gate = GDOMAINS | GZONES;
  1157.   else if (strncmp(v,"none",4) == 0)
  1158.     gate = 0;
  1159.  
  1160. } /* getgate */
  1161. #endif
  1162.  
  1163. static void set_colors(char *keyword,char *value)
  1164. {
  1165.   static struct _nentry ctab[] = {
  1166.     {"bla",    0},
  1167.     {"blu",    1},
  1168.     {"gre",    2},
  1169.     {"cya",    3},
  1170.     {"red",    4},
  1171.     {"mag",    5},
  1172.     {"yel",    6},
  1173.     {"bro",    6},
  1174.     {"whi",    7},
  1175.     {"gra",    7},
  1176.     {NULL,    0}
  1177.   };
  1178.   enum {F_UNKNOWN,F_NORMAL,F_QUOTE,F_WARN,F_BLOCK,F_INFO,F_HILITE};
  1179.   static struct _nentry ftab[] = {
  1180.     {"normal",    F_NORMAL},
  1181.     {"quote",    F_QUOTE},
  1182.     {"warn",    F_WARN},
  1183.     {"block",    F_BLOCK},
  1184.     {"info",    F_INFO},
  1185.     {"hilite",    F_HILITE},
  1186.     {"highlight",    F_HILITE},
  1187.     {NULL,        F_UNKNOWN}
  1188.   };
  1189.   int color, temp;
  1190.   char *s, *f, *b;
  1191.  
  1192.   f = strtok(value,"/");
  1193.   b = strtok(NULL," \t");
  1194.  
  1195.   s = strlwr(strtok(f, " \t+"));
  1196.   color = numlookup(ctab,s);
  1197.  
  1198.   s = strlwr(strtok(NULL, " \t"));
  1199.   while ((s != NULL) && isspace(*s))
  1200.     s++;
  1201.   if ((s != NULL) && (strncmp(s, "int", 3) == 0))    /* intense */
  1202.     color |= 8;
  1203.  
  1204.   temp = numlookup(ctab,b);
  1205.   color |= (temp << 4);
  1206.  
  1207.   switch (numlookup(ftab,keyword)) {
  1208.     case F_NORMAL:    co_normal = color;    break;
  1209.     case F_QUOTE:    co_quote = color;    break;
  1210.     case F_WARN:    co_warn = color;    break;
  1211.     case F_BLOCK:    co_block = color;    break;
  1212.     case F_INFO:    co_info = color;    break;
  1213.     case F_HILITE:    co_hilite = color;    break;
  1214.   } /* switch */
  1215.  
  1216. } /* set_colors */
  1217.  
  1218. /*
  1219.  * Check if an origin line is ok and log a warning if it is too long
  1220.  */
  1221.  
  1222. static void verifyorigin(char *origin, ADDRESS addr)
  1223. {
  1224.   char buffer[200];
  1225.  
  1226.   formatorigin(buffer, origin, addr);
  1227.   if (strlen(buffer) > 80) {
  1228.     strcpy(&buffer[50],"...");        /* truncate the origin line with ... */
  1229.     log(WARN,"Origin line too long: '%s'",buffer);
  1230.   } /* if */
  1231. } /* verifyorigin */
  1232.  
  1233. static void parseconfig(FILE *fp)
  1234. {
  1235.   char    buffer[TEXTLEN];
  1236.   char   *keyword = NULL;
  1237.   char   *value = NULL;
  1238.   BOOLEAN stripped, skipline;
  1239.   struct _centry *look;
  1240.   struct _ientry *ilook;
  1241.  
  1242.   while (!feof(fp)) {
  1243.     memset(buffer, 0, TEXTLEN);
  1244.  
  1245.     if (fgets(buffer, TEXTLEN, fp) == NULL)
  1246.       return;            /* error reading */
  1247.  
  1248.     do {
  1249.       stripped = FALSE;
  1250.       skipline = TRUE;
  1251.  
  1252.       keyword = strlwr(strtok(buffer, " \t"));
  1253.       if ((*keyword) == ';')    /* comment, go skip line */
  1254.     break;
  1255.  
  1256.       if ((value = strtok(NULL, ";\n\r")) == NULL)
  1257.     break;            /* get rest of line up to end or comment */
  1258.  
  1259.       while (isspace(*value) && !((*value == '\n') || (*value == ';') || (*value == '\r')))
  1260.     value++;            /* skip spaces in front */
  1261.  
  1262.       if (stricmp("application",keyword) == 0) {
  1263.     char *s = strlwr(strtok(value," \t"));
  1264.  
  1265.     if ((stricmp("msged",s) == 0) || (stricmp("msgq",s) == 0)) {
  1266.       strcpy(buffer,strtok(NULL,"\n\r"));
  1267.       stripped = TRUE;
  1268.         } /* if */
  1269.       } /* if */
  1270.  
  1271.       skipline = FALSE;
  1272.     } while (stripped);
  1273.  
  1274.     if (skipline) continue;        /* continue the continue */
  1275.  
  1276.     for (look = configtable;  look->label != NULL;  look++)
  1277.       if (stricmp(look->label,keyword) == 0) {
  1278.     logit(TRUE,keyword,value);
  1279.     (look->action)(keyword,value);
  1280.     skipline = TRUE;
  1281.     break;
  1282.       } /* if */
  1283.  
  1284.     if (skipline) continue;
  1285.  
  1286.     for (ilook = oneinttable;  ilook->label != NULL;  ilook++)
  1287.       if (stricmp(ilook->label,keyword) == 0) {
  1288.     logit(TRUE,keyword,value);
  1289.     *ilook->value = (int) strtol(value,NULL,0);
  1290.     skipline = TRUE;
  1291.     break;
  1292.       } /* if */
  1293.  
  1294.     if (skipline) continue;
  1295.  
  1296.     logit(FALSE,keyword,value);
  1297.  
  1298.   } /* while */
  1299.  
  1300. } /* parseconfig */
  1301.  
  1302. /*
  1303.  * Create CONFIG.BBS
  1304.  */
  1305.  
  1306. static void createconfigbbs(void)
  1307. {
  1308.   char name[PATHLEN];
  1309.   CONFIGRECORD *config = NULL;
  1310.   BYTE b, e;
  1311.   int conf = -1;
  1312.   BYTE netmailboard = 0;
  1313.  
  1314.   if ((config = calloc(sizeof(CONFIGRECORD),1)) == NULL) {
  1315.     log(ERR,"No memory to create CONFIG.BBS",NULL);
  1316.     goto leave;
  1317.   } /* if */
  1318.  
  1319.   strcpy(name,bbspath);
  1320.   strcat(name,"config.bbs");
  1321.   log(INFO,"Creating '%s'", name);
  1322.  
  1323.   if ((conf = creat(name,S_IREAD|S_IWRITE)) == -1) {
  1324.     log(ERR,"Could not create '%s'", name);
  1325.     goto leave;
  1326.   } /* if */
  1327.  
  1328.   strncpy(config->netpath,newnetpath,66);
  1329.   c2p_str(config->netpath);
  1330.   strncpy(config->originline,origin,60);
  1331.   c2p_str(config->originline);
  1332.   strncpy(config->sysopname,username,35);
  1333.   c2p_str(config->sysopname);
  1334.  
  1335.   config->uselastread = YES;
  1336.   config->matrixzone = thisnode[0].zone;
  1337.   if (thisnode[0].point) {
  1338.     config->matrixnet  = pointnet;
  1339.     config->matrixnode = thisnode[0].point;
  1340.   } else {
  1341.     config->matrixnet  = thisnode[0].net;
  1342.     config->matrixnode = thisnode[0].node;
  1343.   } /* else */
  1344.   /* config->usezonegates = 1; */
  1345.  
  1346.   e = addresses > 5 ? 5 : addresses;    /* copy over aka's */
  1347.   for (b=1;  b < e;  b++) {
  1348.     config->akazone[b-1] = thisnode[b].zone;
  1349.     config->akanode[b-1] = thisnode[b].node;
  1350.     config->akanet[b-1] = thisnode[b].net;
  1351.     config->akapoint[b-1] = thisnode[b].point;
  1352.   }
  1353.  
  1354.   for (b = 0;  b < areas;  b++) {
  1355.     BYTE board = arealist[b].board-1;        /* index of board */
  1356.  
  1357.     strncpy(config->boardrec[board].name,arealist[b].description,16);
  1358.     c2p_str(config->boardrec[board].name);
  1359.     config->boardrec[board].combined = YES;
  1360.     config->boardrec[board].readseclvl = 5;
  1361.     config->boardrec[board].writeseclvl = 10;
  1362.     config->boardrec[board].sysopseclvl = 100;
  1363.  
  1364.     if (arealist[b].echomail)
  1365.       config->boardrec[board].typ = 3;
  1366.     else if (arealist[b].netmail) {
  1367.       config->boardrec[board].typ = 1;
  1368.       netmailboard = board+1;
  1369.     } /* else */
  1370.     if (arealist[b].msgbits.is_priv)
  1371.       config->boardrec[board].kinds = 1;    /* Private */
  1372.                 /* default is 0, which is "both" */
  1373.   } /* for */
  1374.   config->netmailboard = netmailboard;
  1375.   config->deffgcolor = 7;
  1376.  
  1377.   if (write(conf,(char *)config,sizeof(CONFIGRECORD)) != sizeof(CONFIGRECORD))
  1378.     log(ERR,"Error writing to '%s'", name);
  1379.  
  1380. leave:
  1381.   if (config != NULL)
  1382.     ptrfree(config);
  1383.   if (conf != -1)
  1384.     if (close(conf) == -1)
  1385.       log(ERR,"Error closing '%s'", name);
  1386.  
  1387. } /* createconfigbbs */
  1388.  
  1389. /*
  1390.  * Read CONFIG.BBS
  1391.  */
  1392.  
  1393. static void readconfigbbs(void)
  1394. {
  1395.   char name[PATHLEN];
  1396.   CONFIGRECORD *config = NULL;
  1397.   BYTE b;
  1398.   int conf = -1;
  1399.  
  1400.   if ((config = calloc(sizeof(CONFIGRECORD),1)) == NULL) {
  1401.     log(ERR,"No memory to load CONFIG.BBS",NULL);
  1402.     goto leave;
  1403.   } /* if */
  1404.  
  1405.   strcpy(name,bbspath);
  1406.   strcat(name,"config.bbs");
  1407.   if ((conf = open(name,O_RDWR|O_BINARY,S_IREAD|S_IWRITE)) == -1) {
  1408.     log(ERR,"Could not open '%s'", name);
  1409.     goto leave;
  1410.   } /* if */
  1411.  
  1412.   log(INFO,"Reading '%s'", name);
  1413.   if (read(conf,(char *)config,sizeof(CONFIGRECORD)) != sizeof(CONFIGRECORD)) {
  1414.     log(ERR,"Error reading '%s'", name);
  1415.     goto leave;
  1416.   } /* if */
  1417.  
  1418.   for (b = 0;  b < BLIM;  b++) {
  1419.     p2c_strn(config->boardrec[b].name,16);
  1420.     if (*config->boardrec[b].name != EOS) {
  1421.       BYTE type, bits = 0;
  1422.  
  1423.       switch (config->boardrec[b].typ) {
  1424.     case 1:    type = A_NETM;    break;    /* Netmail */
  1425.     case 3:    type = A_ECHO;  break;    /* Echomail */
  1426.     default:type = A_LOCAL;    break;    /* Standard or Email */
  1427.       } /* switch */
  1428.  
  1429.       if (config->boardrec[b].kinds == 1)    /* Private? */
  1430.     bits |= F_PRIV;
  1431.  
  1432.       addarea(NULL, config->boardrec[b].name, b+1, type, bits, config->useaka[b], NULL);
  1433.     } /* if */
  1434.   } /* for */
  1435.  
  1436.   if (*config->sysopname != EOS) {
  1437.     if (username != NULL) ptrfree(username);
  1438.     p2c_strn(config->sysopname,35);
  1439.     username = strdup(config->sysopname);
  1440.   } /* if */
  1441.  
  1442.   if (*config->originline != EOS) {
  1443.     if (origin != NULL) ptrfree(origin);
  1444.     p2c_strn(config->originline,60);
  1445.     origin = strdup(config->originline);
  1446.   } /* if */
  1447.  
  1448.   thisnode[0].zone = config->matrixzone;
  1449.   thisnode[0].net  = config->matrixnet;
  1450.   thisnode[0].node = config->matrixnode;
  1451.   thisnode[0].point = config->matrixpoint;    /* from 2.61 */
  1452.   if (thisnode[0].net != 0)
  1453.     addresses = 1;
  1454.  
  1455.   for (b=0;  b < 5;  b++)            /* from 2.61 */
  1456.     if ((config->akanet[b] != 0) && (addresses <= MAXAKA)) {
  1457.       thisnode[addresses].zone = config->akazone[b];
  1458.       thisnode[addresses].net  = config->akanet[b];
  1459.       thisnode[addresses].node = config->akanode[b];
  1460.       thisnode[addresses].point = config->akapoint[b];
  1461.       ++addresses;
  1462.     }
  1463.  
  1464.   co_normal = config->deffgcolor | (config->defbgcolor << 4);
  1465.  
  1466.   if (*config->quotestr != EOS) {
  1467.     char *pos;
  1468.     if (quotestr != NULL) ptrfree(quotestr);
  1469.     p2c_strn(config->quotestr,3);
  1470.     quotestr = strdup(config->quotestr);
  1471.     if ((pos = strchr(quotestr,'\01')) != NULL)
  1472.       *pos = '&';        /* all initials */
  1473.   } /* if */
  1474.  
  1475. leave:
  1476.   if (config != NULL)
  1477.     ptrfree(config);
  1478.   if (conf != -1)
  1479.     close(conf);
  1480.  
  1481. } /* readconfigbbs */
  1482.  
  1483. /*
  1484.  * Read MESSAGES.RA
  1485.  */
  1486.  
  1487. static void readmessagesra(void)
  1488. {
  1489.   char name[PATHLEN];
  1490.   RA_BOARDRECORD board;
  1491.   BYTE b;
  1492.   int conf = -1;
  1493.  
  1494.   strcpy(name,bbspath);
  1495.   strcat(name,"messages.ra");
  1496.   if ((conf = open(name,O_RDWR|O_BINARY,S_IREAD|S_IWRITE)) == -1) {
  1497.     log(ERR,"Could not open '%s'", name);
  1498.     goto leave;
  1499.   } /* if */
  1500.  
  1501.   log(INFO,"Reading '%s'", name);
  1502.  
  1503.   b = 0;
  1504.   while (!eof(conf)) {
  1505.     ++b;
  1506.     (void)read(conf, &board, sizeof(board));
  1507.     p2c_strn(board.name,40);
  1508.     if (*board.name != EOS) {
  1509.       BYTE type, bits = 0;
  1510.  
  1511.       switch (board.type) {
  1512.     case RA_NetMail:    type = A_NETM;    break;
  1513.     case RA_EchoMail:    type = A_ECHO;  break;
  1514.     default:        type = A_LOCAL;    break;
  1515.       } /* switch */
  1516.  
  1517.       if (board.kinds == RA_Private)    /* Private? */
  1518.     bits |= F_PRIV;
  1519.  
  1520.       addarea(NULL, board.name, b, type, bits, board.aka, NULL);
  1521.     } /* if */
  1522.   } /* while */
  1523.  
  1524. leave:
  1525.   if (conf != -1)
  1526.     close(conf);
  1527.  
  1528. } /* readmessagesra */
  1529.  
  1530. /*
  1531.  * Read CONFIG.RA
  1532.  */
  1533.  
  1534. static void readconfigra(void)
  1535. {
  1536.   char name[PATHLEN];
  1537.   RA_CONFIG *config = NULL;
  1538.   int conf = -1;
  1539.   int c;
  1540.  
  1541.   if ((config = calloc(sizeof(RA_CONFIG),1)) == NULL) {
  1542.     log(ERR,"No memory to load CONFIG.RA",NULL);
  1543.     goto leave;
  1544.   } /* if */
  1545.  
  1546.   strcpy(name,bbspath);
  1547.   strcat(name,"config.ra");
  1548.   if ((conf = open(name,O_RDWR|O_BINARY,S_IREAD|S_IWRITE)) == -1) {
  1549.     log(ERR,"Could not open '%s'", name);
  1550.     goto leave;
  1551.   } /* if */
  1552.  
  1553.   log(INFO,"Reading '%s'", name);
  1554.   if (read(conf,(char *)config,sizeof(RA_CONFIG)) != sizeof(RA_CONFIG)) {
  1555.     log(ERR,"Error reading '%s'", name);
  1556.     goto leave;
  1557.   } /* if */
  1558.  
  1559.   if (*config->sysop != EOS) {
  1560.     if (username != NULL) ptrfree(username);
  1561.     p2c_strn(config->sysop,35);
  1562.     username = strdup(config->sysop);
  1563.   } /* if */
  1564.  
  1565.   if (*config->origin_line != EOS) {
  1566.     if (origin != NULL) ptrfree(origin);
  1567.     p2c_strn(config->origin_line,60);
  1568.     origin = strdup(config->origin_line);
  1569.   } /* if */
  1570.  
  1571.   for (c=0;  c < 10;  c++)
  1572.     if ((config->address[c].net != 0) && (addresses <= MAXAKA)) {
  1573.       thisnode[addresses].zone = config->address[c].zone;
  1574.       thisnode[addresses].net  = config->address[c].net;
  1575.       thisnode[addresses].node = config->address[c].node;
  1576.       thisnode[addresses].point = config->address[c].point;
  1577.       ++addresses;
  1578.     }
  1579.  
  1580.   co_normal = config->norm_fore | (config->norm_back << 4);
  1581.   co_warn = config->hi_fore | (config->hi_back << 4);
  1582.   co_block = config->stat_fore | (config->stat_back << 4);
  1583.   co_info = config->wind_fore | (config->wind_back << 4);
  1584.   co_quote = config->bar_fore | (config->bar_back << 4);
  1585.   co_hilite = config->border_fore | (config->border_back << 4);
  1586.  
  1587.   if (*config->quote_string != EOS) {
  1588.     char *pos;
  1589.     if (quotestr != NULL) ptrfree(quotestr);
  1590.     p2c_strn(config->quote_string,15);
  1591.     quotestr = strdup(config->quote_string);
  1592.     if ((pos = strchr(quotestr,'\01')) != NULL)
  1593.       *pos = '&';        /* all initials */
  1594.   } /* if */
  1595.  
  1596. leave:
  1597.   if (config != NULL)
  1598.     ptrfree(config);
  1599.   if (conf != -1)
  1600.     close(conf);
  1601.  
  1602. } /* readconfigra */
  1603.  
  1604. /*
  1605.  * Read RA configs
  1606.  */
  1607.  
  1608. static void readraconfigs(void)
  1609. {
  1610.   readconfigra();
  1611.   readmessagesra();
  1612. } /* readraconfigs */
  1613.  
  1614. /*
  1615.  * Look for the file ECHOORIG.CTL
  1616.  * All areas must have been defined when this is called
  1617.  */
  1618.  
  1619. void checkorig(void)
  1620. {
  1621.   char buf[TEXTLEN];
  1622.   char *s;
  1623.   FILE *orig;
  1624.   BYTE board;
  1625.   int c;
  1626.  
  1627.   strcpy(buf,bbspath);
  1628.   strcat(buf,"echoorig.ctl");
  1629.  
  1630.   if ((orig = fopen(buf,"rt")) == NULL)
  1631.     return;                /* not found */
  1632.   log(INFO,"Reading '%s'",buf);
  1633.  
  1634.   while (fgets(buf, TEXTLEN, orig) != NULL) {
  1635.     c = strlen(buf)-1;
  1636.     if (buf[c] == '\n')            /* strip the newline */
  1637.       buf[c] = EOS;
  1638.  
  1639.     s = buf;
  1640.     while (isspace(*s)) s++;        /* skip spaces */
  1641.     if ((board = atoi(s)) == 0)        /* get number */
  1642.       continue;
  1643.     while (isdigit(*s)) s++;        /* skip number */
  1644.     while (isspace(*s)) s++;        /* skip spaces */
  1645.  
  1646.     for (c = 0;  c < areas;  c++)
  1647.       if (board == arealist[c].board) {
  1648.     arealist[c].areaorig = strdup(s);    /* override default origin */
  1649.     verifyorigin(s,thisnode[0]);
  1650.     break;
  1651.       } /* if */
  1652.  
  1653.   } /* while */
  1654.  
  1655.   fclose(orig);
  1656.  
  1657. } /* checkorig */
  1658.  
  1659. /*
  1660.  * D'Bridge code courtesy of Fredrik Chabot (2:281/5.10)
  1661.  */
  1662.  
  1663. #ifdef DBRIDGE
  1664. typedef struct {
  1665.   char allocated;
  1666.   char tag[17];
  1667.   char ECHOmail_tag[57];
  1668. } _aa1;
  1669.  
  1670. typedef struct {
  1671.   char description[41];
  1672.   int  group;
  1673.   char storage;
  1674.   char directory_path[49];
  1675.   char kind;
  1676.   int  quick_area;
  1677.   char default_private;
  1678.   char tiny_seenbys;
  1679.   char origin_line[57];
  1680.   char depault_priority;
  1681.   int  alias_zone,
  1682.        alias_net,
  1683.        alias_node,
  1684.        alias_point;
  1685.   int  area_purge,
  1686.        area_preserve,
  1687.        area_security;
  1688.   char area_archive[57];
  1689.   char forward_to[5][57];
  1690. } _aa2;
  1691.  
  1692. /*
  1693.  * Read D'Bridge config
  1694.  */
  1695.  
  1696. static void readdbridgeprm()
  1697. {
  1698. /*
  1699.       Field                  Line/Column   Description
  1700.       ------------------------------------------------------------------------- 
  1701.       PARAMETER FILE VERSION     1/1       Current software version
  1702.       NETWORK MAIL STORAGE       2/1       NETmail storage method: F, T or Q
  1703.       DBMAILER OVERLAY EMS?      2/2       Copy DBMAILER.OVR to EMS?  1 or 0
  1704.       DBEDIT OVERLAY EMS?        2/3       Copy DBEDIT.OVR to EMS? 1 or 0
  1705.       DBMAILER PROGRAM SIZE      2/4       Total memory (in K)
  1706.       DBMAILER WORKRAM SIZE      2/11      WorkRAM (in K)
  1707.       NETWORK MAIL DIRECTORY     3/1       Fido-style NETmail directory path
  1708.       INBOUND FILES DIRECTORY    4/1       Inbound files directory path
  1709.       PACKET DIRECTORY           5/1       Temporary packet directory path
  1710.       QUEUE DIRECTORY            6/1       Disk-based queue directory path
  1711.       SCRIPT DIRECTORY           7/1       Script file directory path
  1712.       BADECHO DIRECTORY          8/1       BADECHO directory path (Fido-style)
  1713.       NEWECHO DIRECTORY          9/1       New ECHOmail base directory path
  1714.       QUICKBBS DIRECTORY        10/1       QuickBBS directory path
  1715.       SJF DIRECTORY             11/1       SJF directory path
  1716.       DOWNLOAD DIRECTORY        12/1       Terminal download directory path
  1717.       OUTBOUND MAIL ARCHIVE     13/1       Outbound NETmail archive filename
  1718.       NETWORK MAIL ARCHIVE      14/1       NETmail archive filename
  1719.       SYSTEM NAME               15/1       Primary system name 
  1720.       OPERATOR NAME             16/1       Primary operator name 
  1721.       ZONE                      17/1       Zone address 
  1722.       NET                       17/8       Net address
  1723.       NODE                      17/15      Node address
  1724.       POINT                     17/22      Point address
  1725. --------------------------------------------------------------------
  1726.       QBBSNETMAIL               17/85      **NIET GEDOCUMENTEERD**
  1727.  
  1728. */
  1729.  
  1730.   FILE *fd, *fopen();
  1731.   char buffer[512], *line,
  1732.        netmailst;
  1733.   int  qbbsnetmail;
  1734.  
  1735.   if((fd=fopen("dbridge.prm","rt"))==NULL){
  1736.     log(ERR,"Could not open dbridge.prm",NULL);
  1737.   }
  1738.  
  1739.   line=fgets(buffer,512,fd); /*  1 */
  1740.   /*    dbridge=strdup(line);   */
  1741.   line=fgets(buffer,512,fd); /*  2 */
  1742.   netmailst=line[0];
  1743.   line=fgets(buffer,512,fd); /*  3 */
  1744.   /*    netmaildir=strdup(line);   */
  1745.   line=fgets(buffer,512,fd); /*  4 */
  1746.   line=fgets(buffer,512,fd); /*  5 */
  1747.   line=fgets(buffer,512,fd); /*  6 */
  1748.   line=fgets(buffer,512,fd); /*  7 */
  1749.   line=fgets(buffer,512,fd); /*  8 */
  1750.   /*    badechodir=strdup(line);  */
  1751.   line=fgets(buffer,512,fd); /*  9 */
  1752.   line=fgets(buffer,512,fd); line[strlen(line)-1]=0;  /* 10 */
  1753.   bbspath=strdup(line);
  1754.   line=fgets(buffer,512,fd); /* 11 */
  1755.   line=fgets(buffer,512,fd); /* 12 */
  1756.   line=fgets(buffer,512,fd); /* 13 */
  1757.   line=fgets(buffer,512,fd); /* 14 */
  1758.   line=fgets(buffer,512,fd); /* 15 */
  1759.   /*    sysname=strdup(line);  */
  1760.   line=fgets(buffer,512,fd); line[strlen(line)-1]=0;/* 16 */
  1761.   username=strdup(line);
  1762.   line=fgets(buffer,512,fd); /* 17 */
  1763.   thisnode[0].zone=atoi(line);
  1764.   thisnode[0].net=atoi(line+7);
  1765.   thisnode[0].node=atoi(line+14);
  1766.   thisnode[0].point=atoi(line+21);
  1767.   if (thisnode[0].net != 0)
  1768.     addresses = 1;
  1769.   qbbsnetmail=atoi(line+84);
  1770.  
  1771.   if(netmailst=='Q'){
  1772.     insertarea = 0;   /* insert at front */
  1773.     addarea("Net-Mail", NULL, qbbsnetmail, A_NETM, 0, 0, NULL);
  1774.   }
  1775.   fclose(fd);
  1776. } /* readdbridgeprm */
  1777.  
  1778. /*
  1779.  * Read D'Bridge areas
  1780.  */
  1781.  
  1782. static void readdbridgeareas(void)
  1783. {
  1784.   _aa1 aa1;
  1785.   _aa2 aa2;
  1786.   int fdaa1, fdaa2;
  1787.   if((fdaa1=_open("Dbridge.aa1",O_BINARY | O_RDONLY))==-1)
  1788.     log(ERR,"Could not open dbridge.aa1",NULL);
  1789.  
  1790.   if((fdaa2=_open("Dbridge.aa2",O_BINARY | O_RDONLY))==-1)
  1791.     log(ERR,"Could not open dbridge.aa2",NULL);
  1792.  
  1793.   while( _read(fdaa1,&aa1,sizeof(aa1))==sizeof(aa1) ){
  1794.     _read(fdaa2,&aa2,sizeof(aa2));
  1795.     p2c_str(aa1.tag);
  1796.     p2c_str(aa1.ECHOmail_tag);
  1797. /*    printf("'%s' - ",aa1.tag); */
  1798.  
  1799.     p2c_str(aa2.description);
  1800.     p2c_str(aa2.directory_path);
  1801.     p2c_str(aa2.origin_line);
  1802. /*     printf("%d - '%s' - '%s'\n",aa2.quick_area,aa2.description,aa2.origin_line); */
  1803.     addarea(aa1.tag, aa2.description, aa2.quick_area, A_ECHO, 0, 0, aa2.origin_line);
  1804.   }
  1805.   _close(fdaa1);
  1806.   _close(fdaa2);
  1807. } /* readdbridgeareas */
  1808.  
  1809. static void readdbridgeconfigs(void)
  1810. {
  1811.   readdbridgeareas();
  1812.   readdbridgeprm();
  1813. } /* readdbridgeconfigs */
  1814.  
  1815. #endif /* DBRIDGE */
  1816.